// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#pragma once

#include <cstdio>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>

#include <rapidjson/document.h>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/bithumb/api_util/order_manager.h"
#include "coin2/exchange/bithumb/symbology/currency.h"
#include "coin2/exchange/bithumb/symbology/product.h"

namespace coin2::exchange::bithumb::order_v2 {

class BithumbParser : public base::order::BaseParser {
  using OrderCacheManager = coin2::exchange::bithumb::api_util::OrderManager;

 public:
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& doc) override;
  bool ParseRawBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);
  void SetOrderCacheManager(OrderCacheManager* order_mgr) { order_mgr_ = order_mgr; }

 private:
  void ParseSubmitResponse();
  void ParseCancelResponse();
  void ParseRestOpenOrders();
  void ParseRestFillOrders();
  void ParseRestAccountBalance();
  void ParseWsMessage();

  ProductOrderBundle ParseRestOrderInfoListV1(const JsonValue& data);
  ProductOrderBundle ParseRestOrderInfoListV2(const JsonValue& data);
  ProductOrderBundle ParseRestOrderInfoListV3(const JsonValue& data);
  ProductFillBundle ParseRestFillInfoListV1(const JsonValue& data);
  ProductFillBundle ParseRestFillInfoListV2(const JsonValue& data);
  coin::proto::ProductOrderElement ParseOrderInfo(const JsonValue& data);
  coin::proto::ProductOrderElement
  AddVirtualOrder(std::string symbol, coin::proto::OrderSide side, bool is_live);
  auto ParseHeader(const std::shared_ptr<AsioHttpContext>&) const -> std::optional<std::string>;

 private:
  OrderCacheManager* order_mgr_ = nullptr;
  std::string current_native_symbol_;
  std::map<std::string, std::set<std::string>> known_fill_ids_;
  std::map<std::string, bool> not_first_fill_query_;
  std::map<std::string, bool> not_first_order_query_;
  std::map<int64_t, bool> seen_in_open_order_list_;
  std::string current_order_id_;
  bool is_account_balance_initialized_ = false;
};

}  // namespace coin2::exchange::bithumb::order_v2
